/**
 * create by zhangpu
 * date:2015年3月2日
 */
package com.acooly.module.openapi.client.provider.hx;

import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.AbstractApiServiceClient;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.exception.ApiServerException;
import com.acooly.module.openapi.client.api.marshal.ApiMarshal;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.PostRedirect;
import com.acooly.module.openapi.client.api.transport.Transport;
import com.acooly.module.openapi.client.provider.hx.domain.HxNotify;
import com.acooly.module.openapi.client.provider.hx.domain.HxRequest;
import com.acooly.module.openapi.client.provider.hx.domain.HxResponse;
import com.acooly.module.openapi.client.provider.hx.enums.HxServiceEnum;
import com.acooly.module.openapi.client.provider.hx.marshall.HxRedirectMarshall;
import com.acooly.module.openapi.client.provider.hx.marshall.HxRedirectPostMarshall;
import com.acooly.module.openapi.client.provider.hx.marshall.HxRequestMarshall;
import com.acooly.module.openapi.client.provider.hx.marshall.HxResponseUnmarshall;
import com.acooly.module.openapi.client.provider.hx.marshall.HxSignMarshall;
import com.acooly.module.openapi.client.provider.hx.message.HxNetbankPayResponse;

import org.apache.axis.client.Call;
import org.apache.axis.encoding.XMLType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

import javax.annotation.Resource;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;

import lombok.extern.slf4j.Slf4j;

/**
 * 上海银行P2P存管ApiService执行器  外部业务禁止使用
 *
 * @author zhangpu
 */
@Slf4j
@Component("hxApiServiceClient")
public class HxApiServiceClient
        extends AbstractApiServiceClient<HxRequest, HxResponse, HxNotify, HxNotify> {

    public static final String PROVIDER_NAME = "hx";

    @Resource(name = "hxHttpTransport")
    private Transport transport;
    @Resource(name = "hxRequestMarshall")
    private HxRequestMarshall requestMarshal;
    @Resource(name = "hxRedirectMarshall")
    private HxRedirectMarshall redirectMarshal;
    @Resource(name = "hxRedirectPostMarshall")
    private HxRedirectPostMarshall hxRedirectPostMarshall;
    @Resource(name = "hxSignMarshall")
    private HxSignMarshall signMarshall;

    @Autowired
    private HxResponseUnmarshall responseUnmarshal;

    //@Autowired
    //private HxNotifyUnmarshall notifyUnmarshal;

    @Autowired
    private HxProperties hxProperties;

    @Override
    public HxResponse execute(HxRequest request) {
        try {
            beforeExecute(request);
            if(Strings.isBlank(request.getGatewayUrl())) {
                request.setGatewayUrl(hxProperties.getGatewayUrl());
            }
            String url = request.getGatewayUrl();
            String requestMessage = getRequestMarshal().marshal(request);
            log.info("请求报文: {}", requestMessage);
            if(HxServiceEnum.hxNetbankPay.code().equals(request.getService())){
                HxNetbankPayResponse hxNetbankPayResponse = new HxNetbankPayResponse();
                hxNetbankPayResponse.setNetBankHtml(requestMessage);
                return  hxNetbankPayResponse;
            }
            String responseMessage = webServicExchange(requestMessage, url, request.getNamespaceUrl(), request.getLocalPart(), request.getParamName());
            HxResponse t = getResponseUnmarshal().unmarshal(responseMessage, request.getService());
            afterExecute(t);
            return t;
        } catch (ApiServerException ose) {
            log.error("服务器:" + ose.getMessage(), ose);
            throw ose;
        } catch (ApiClientException oce) {
            log.error("客户端:" + oce.getMessage(), oce);
            throw oce;
        } catch (Exception e) {
            log.error("内部错误:" + e.getMessage(), e);
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }


    @Override
    public PostRedirect redirectPost(HxRequest request) {
        try {
            beforeExecute(request);
            PostRedirect postRedirect = hxRedirectPostMarshall.marshal(request);
            return postRedirect;
        } catch (ApiServerException ose) {
            log.error("服务器:" + ose.getMessage(), ose);
            throw ose;
        } catch (ApiClientException oce) {
            log.error("客户端:" + oce.getMessage(), oce);
            throw oce;
        } catch (Exception e) {
            log.error("内部错误:" + e.getMessage(), e);
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }

    @Override
    protected ApiMarshal<String, HxRequest> getRequestMarshal() {
        return this.requestMarshal;
    }

    @Override
    protected ApiUnmarshal<HxResponse, String> getResponseUnmarshal() {
        return this.responseUnmarshal;
    }

    @Override
    protected ApiUnmarshal<HxNotify, Map<String, String>> getNoticeUnmarshal() {
        //return this.notifyUnmarshal;
        return null;
    }

    @Override
    protected ApiMarshal<String, HxRequest> getRedirectMarshal() {
        return this.redirectMarshal;
    }

    @Override
    protected Transport getTransport() {
        return this.transport;
    }

    @Override
    protected ApiUnmarshal<HxNotify, Map<String, String>> getReturnUnmarshal() {
        //return this.notifyUnmarshal;
        return null;
    }

    @Override
    public String getName() {
        return PROVIDER_NAME;
    }

    public String webServicExchange(String requestMessage, String url, String namespceUrl, String localPart, String paramName) throws Exception{
        org.apache.axis.client.Service s = new org.apache.axis.client.Service();
        Call call = null;
        try {
            call = (Call) s.createCall();
        } catch (ServiceException e) {
            log.info("加载web servic组件失败，error:{}",e.getMessage());
        }
        call.setTargetEndpointAddress(url);
        QName qName = new QName(namespceUrl, localPart);
        call.setOperationName(qName);
        call.setUseSOAPAction(true);
        call.setTimeout(new Integer(5000));
        //这下面两行一定要加上，否则接收在服务器端收不到。
        call.addParameter(paramName, XMLType.XSD_STRING, ParameterMode.IN);
        call.setReturnType(XMLType.XSD_STRING);
        return (String) call.invoke(new Object[] { requestMessage });
    }

}
